% ALGORITHM
%
% - load the manual events
% - load the events from the raw dataset
% - if there is matching between the number of events then associate them,
%   otherwise raise an error
%
function LoadDatasets( tSVMTrainer, strDatasetFromWebsite, strManualDataset, bDoInteractiveTraining )
	%
	if( nargin == 3 )
		%
		bDoInteractiveTraining = false;
		%
	end;%
	%
	%
	% -----------------------------------------------------------------------------------
	% load the manual dataset
	fprintf('Starting loading the manual dataset...\n');
	%
	[	astrManualEventsClasses,	...
		afManualEventsJulianDates,	...
		astrManualEventsNotes	] =	...
			tSVMTrainer.LoadManualDataset( strManualDataset );
	%
	iNumberOfManualEvents = numel(afManualEventsJulianDates);
	%
	% DEBUG
	fprintf('\n\n**********************************************************\nLoaded the following %d manual events:\n', ...
			iNumberOfManualEvents);
	for iEvent = 1:iNumberOfManualEvents;
		fprintf('%s\t%s\n', astrManualEventsClasses{iEvent}, Time.JulianDateToString(afManualEventsJulianDates(iEvent)){1} );
	end;%
	%
	%
	%
	%
	% -----------------------------------------------------------------------------------
	% load the dataset from raw data
	fprintf('Starting loading the raw dataset...\n');
	%
	aafRawData			= load(strDatasetFromWebsite);
	atOccupancyEvents	= PeopleCounters.TransformRawDataIntoEvents( aafRawData );
	%
	iNumberOfEventsFromRawData = numel(atOccupancyEvents);
	%
	% DEBUG
	fprintf('\n\n**********************************************************\nLoaded the following %d raw data events (note: they still do not have associated classes):\n',	...
			iNumberOfManualEvents);
	for iEvent = 1:iNumberOfEventsFromRawData;
		fprintf('%s - %s\n', Time.JulianDateToString(atOccupancyEvents(iEvent).fStartingJulianDate){1}, Time.JulianDateToString(atOccupancyEvents(iEvent).fEndingJulianDate){1} );
	end;%
	fprintf('\n\n**********************************************************\nStarting the association process:\n');
	%
	%
	%
	%
	%
	% -----------------------------------------------------------------------------------
	% compute the distances between each raw / measured events couple (rows = raw) 
	aafRawToMeasuredEventsDistancesInSeconds = zeros( iNumberOfEventsFromRawData, iNumberOfManualEvents );
	%
	for iRawEvent		= 1:iNumberOfEventsFromRawData;
	for iManualEvent	= 1:iNumberOfManualEvents;
		%
		aafRawToMeasuredEventsDistancesInSeconds(iRawEvent, iManualEvent) =											...
			min(		abs( atOccupancyEvents(iRawEvent).fEndingJulianDate - afManualEventsJulianDates(iManualEvent) )	...
					/	Time.GetJulianSecond(),																		...
					999 );
		%
	end;%
	end;%
	%
	% before assigning the manual measurements we set every raw event as an invalid one
	for iRawEvent = 1:iNumberOfEventsFromRawData;
		%
		% by default, the event is invalid
		atOccupancyEvents(iRawEvent).bIsValid = false;
		%
	end;%
	%
	% now we associate every manual measurement to the corresponding (if existing)
	% raw one
	for iMeasuredEvent = 1:iNumberOfManualEvents;
		%
		% check who is the raw event closer in time
		[ fTimeDistance, iRawEvent ] = 	...
			min( aafRawToMeasuredEventsDistancesInSeconds(:, iMeasuredEvent) );
		%
		% if the time is too big for everything then discard the measured event, otherwise
		% do the association
		if( fTimeDistance < 5 )
			%
			% before doing the association check if the raw event has been asked to be discarded
			if( ~tSVMTrainer.ShouldThisEventBeDiscarded( astrManualEventsClasses{iMeasuredEvent} ) )
				%
				atOccupancyEvents(iRawEvent).strMeasuredClass	= astrManualEventsClasses{iMeasuredEvent};
				%
				% in case, do the interactive check
				%
				bUserHasAcceptedTheCurrentEvent = true;
				%
				if( bDoInteractiveTraining )
					%
					close all;
					atOccupancyEvents(iRawEvent).Plot();
					%
					strInput = sprintf('Associate %s - %s with %s (distance in seconds = %.2f)? 0 = no, otherwise = yes  \n',	...
							Time.JulianDateToString(atOccupancyEvents(iRawEvent).fStartingJulianDate){1},		... 
							Time.JulianDateToString(atOccupancyEvents(iRawEvent).fEndingJulianDate){1},			... 
							Time.JulianDateToString(afManualEventsJulianDates(iMeasuredEvent)){1},				...
							fTimeDistance																		);
					%
					bUserHasAcceptedTheCurrentEvent = input(strInput);
					%
				end;%
				%
				if( bUserHasAcceptedTheCurrentEvent )
					%
					atOccupancyEvents(iRawEvent).bIsValid = true;
					%
					% DEBUG
					fprintf('%s - %s has been associated to %s (distance in seconds = %.2f)\n',					...
							Time.JulianDateToString(atOccupancyEvents(iRawEvent).fStartingJulianDate){1},		... 
							Time.JulianDateToString(atOccupancyEvents(iRawEvent).fEndingJulianDate){1},			... 
							Time.JulianDateToString(afManualEventsJulianDates(iMeasuredEvent)){1},				...
							fTimeDistance																		);
					%
				else%
					%
					% DEBUG
					fprintf('DISCARDED!\n');
					%
				end;%
				%
			else%
				%
				fprintf('The raw occupancy event %d (%s - %s) has been discarded because its class is outside the pre-defined thresholds\n',	...
						iRawEvent,																			...
						Time.JulianDateToString(atOccupancyEvents(iRawEvent).fStartingJulianDate){1},		... 
						Time.JulianDateToString(atOccupancyEvents(iRawEvent).fEndingJulianDate){1}			);
				%
			end;%
			%
		else%
			%
			fprintf('The measured occupancy event %d (%s - %s) has been discarded because not associated to any raw event\n',	...
					iRawEvent,																			...
					Time.JulianDateToString(atOccupancyEvents(iRawEvent).fStartingJulianDate){1},		... 
					Time.JulianDateToString(atOccupancyEvents(iRawEvent).fEndingJulianDate){1}			);
			%
		end;%
		%
	end;% cycle on the raw events
	%
	% save only the valid events
	tSVMTrainer.atEvents = PeopleCounters.DiscardInvalidEvents( atOccupancyEvents );
	%
end % function

